import Area from '../../sql/module/area/area';
import BlockNumber from '../../sql/module/area/block_number';
import StoreItem from '../../sql/module/factory/storeitem';
import RoomNumber from '../../sql/module/area/room_number';
import Template from '../../sql/module/factory/template';
import ProcureList from '../../sql/module/factory/procure_list';
import Material from '../../sql/module/factory/material';
import TemplateType from '../../sql/module/factory/template_type';
import ImgTemplate from '../../sql/module/factory/img_template';
import User from '../../sql/module/user/user';
import auth from '../../middlewares/auth';
import { Success, ParameterException, NotFoundItem, Repeatedly, Forbbidend } from '../../code/http-exception';
import { ListValidator, NoParames, InfoValidator } from '../../validators/public';
import { Op } from 'sequelize';
import Role from '../../sql/module/user/role';
import { Coordinate, addList } from '../../validators';
import { sequelize } from '../../sql/db';
import ProcureOrder from '../../sql/module/factory/procure_order';
import { PROCURESTATE } from "../../lib/enum";

const router: Api = new Map()

//支付
router.set('/pay', [auth('addIndex'), async (ctx, next) => {
    const v = await new InfoValidator().validate(ctx)
    const UserId = ctx.auth.id
    const orderId = v.get('query.id')
    const where = { UserId, ProcureOrderId: orderId, state: PROCURESTATE.UN_PAY }
    const [affectedCount] = await ProcureList.update({ state: PROCURESTATE.HAS_PAY }, { where })
    if (affectedCount === 0) throw new NotFoundItem('订单内商品为空')
    //支付
    await ProcureOrder.update({ state: 1 }, { where: { UserId, id: orderId } })
    throw new Success()
}])

//退款
router.set('/pay_back', [auth('addIndex'), async (ctx, next) => {
    const v = await new InfoValidator().validate(ctx)
    const UserId = ctx.auth.id
    const orderId = v.get('query.id')
    const where = { UserId, ProcureOrderId: orderId, state: PROCURESTATE.HAS_PAY }
    const [affectedCount] = await ProcureList.update({ state: PROCURESTATE.UN_PAY }, { where })
    if (affectedCount === 0) throw new NotFoundItem('订单内商品为空')
    //支付
    await ProcureOrder.update({ state: 0 }, { where: { UserId, id: orderId } })
    throw new Success()
}])

//确认收货
router.set('/finish', [auth('addIndex'), async (ctx, next) => {
    const v = await new InfoValidator().validate(ctx)
    const UserId = ctx.auth.id
    const id = v.get('query.id')
    const procureOrder = await ProcureOrder.findOne({ where: { UserId, id, state: true } })
    if (!procureOrder) { throw new NotFoundItem() }
    const oldpProcure = await ProcureList.findAll({ where: { ProcureOrderId: procureOrder.dataValues.id, state: PROCURESTATE.IN_TRANSIT } })
    await Promise.all(oldpProcure.map(async item => {
        const { UserId, StoreItemId } = item.dataValues
        if (StoreItemId) {
            await StoreItem.update({ UserId, isSaled: true }, { where: { id: StoreItemId } })
            return item.destroy()
        } else return true
    }))
    const procure = await ProcureList.findAll({ where: { ProcureOrderId: procureOrder.dataValues.id } })
    if (procure.length === 0) { await procureOrder.destroy() }
    else { throw new Forbbidend('部分未发货，请稍后重试') }
    throw new Success()
}])

//用户提交订单
router.set('/addList', [auth('public'), async (ctx, next) => {
    const v = await new addList().validate(ctx)
    const UserId = ctx.auth.id
    let id = v.get('query.id')
    let TemplateId = v.get('query.TemplateId')
    const phone = v.get('query.phone')
    let from = null
    if (id >= 1) {
        //是否存在商品
        const store = await StoreItem.findOne({ where: { id } })
        if (!store) throw new NotFoundItem('商品未发现')
        TemplateId = store.dataValues.TemplateId
        from = store.dataValues.UserId
        //是否已在订单中
        const procure = await ProcureList.findOne({ where: { StoreItemId: id } })
        if (procure) throw new Repeatedly('ID' + id + '已被绑定')
        await store.update({ UserId: null })
    } else {
        const template = await Template.findOne({ where: { id: TemplateId } })
        if (!template) throw new NotFoundItem('模版未发现')
        from = template.dataValues.UserId
        id = null
    }
    const procurenew = await ProcureList.create({
        StoreItemId: id, TemplateId,
        from, UserId, phone, state: PROCURESTATE.UN_CONFIRM
    })
    throw new Success(procurenew)
}])

//用户获取已提交订单
router.set('/inProcureList', [auth('addIndex'), async (ctx, next) => {
    const UserId = ctx.auth.id
    const { rows, count } = await ProcureList.findAndCountAll({
        attributes: ['id', [sequelize.col('Template.id'), 'TemplateId'], [sequelize.col('StoreItem.id'), 'StoreItemId'],
            [sequelize.col('Template.name'), 'name'], [sequelize.col('StoreItem.price'), 'storePrice'], 'state',
            [sequelize.col('From.nickname'), 'nickname'], [sequelize.col('From.id'), 'UserId'], [sequelize.col('Template.price'), 'price'],
            [sequelize.col('Template.TemplateType.name'), 'TemplateType'], "ProcureOrderId", "state_name"],
        where: { UserId },
        include: [{
            model: StoreItem, attributes: []
        },
        { model: Template, attributes: [], include: [{ model: ImgTemplate, attributes: [] }, TemplateType] },
        { model: User, as: 'From', attributes: [] }],
        distinct: true
    })
    throw new Success({ list: rows, total: count })
}])

//用户获取运费订单
router.set('/inProcureOrderList', [auth('addIndex'), async (ctx, next) => {
    const UserId = ctx.auth.id
    const rows = await ProcureOrder.findAll({
        attributes: ["id", "freight", "orderId", "state"],
        where: { UserId },
        include: { model: ProcureList, where: {}, attributes: ['id'] }
    })
    throw new Success(rows)
}])

//用户删除已提交订单
router.set('/back', [auth('addIndex'), async (ctx, next) => {
    const v = await new InfoValidator().validate(ctx)
    const id = v.get('query.id')
    const item = await ProcureList.findOne({ where: { id, state: [PROCURESTATE.UN_CONFIRM, PROCURESTATE.UN_PAY] } })
    if (!item) throw new NotFoundItem('订单未发现或已支付')
    await StoreItem.update({ UserId: item.dataValues.from }, { where: { id: item.dataValues.StoreItemId } })
    await item.destroy()
    throw new Success()
}])

//根据坐标获取最近商家
router.set('/getUserbyCoordinate', [auth('_index'), async (ctx, next) => {
    const v = await new Coordinate().validate(ctx)
    const [latitude, longitude] = v.get('body.latlong').split(',')
    var attributes: any[] = [];
    var location = sequelize.literal(`ST_GeomFromText('POINT(${longitude} ${latitude})')`);
    var distance = sequelize.fn('ST_Distance_Sphere', sequelize.literal('location'), location);
    attributes.push([distance, 'distance']);
    const where = { '$Roles.name$': 'main' }

    const user = await User.findAll({
        attributes: ['id', 'nickname', ...attributes],
        where,
        include: { model: Role, attributes: [], through: { attributes: [] } },
        order: ['distance']
    })
    throw new Success(user)
}])

//获取房间号用于筛选厂家
router.set('/roomNumbers', [auth('_index'), async (ctx, next) => {
    const area = await Area.findAll({
        attributes: { exclude: ['createdAt', 'updatedAt'] },
        include: {
            model: BlockNumber,
            attributes: { exclude: ['createdAt', 'updatedAt'] },
            as: 'children',
            include: {
                //@ts-ignore
                model: RoomNumber,
                attributes: { exclude: ['createdAt', 'updatedAt'] },
                as: 'children'
            }
        },
    })
    throw new Success(area)
}])

//获取区域内厂家
router.set('/users', [auth('_index'), async (ctx, next) => {
    const v = await new NoParames().validate(ctx)
    const RoomNumberId = v.get('query.id')
    const where: any = {}
    RoomNumberId && (where.RoomNumberId = RoomNumberId)
    const user = await User.findAll({
        attributes: ['id', 'nickname'],
        where,
        include: { model: Role, where: { name: 'main' }, attributes: [], through: { attributes: [] } },
        limit: 6
    })
    throw new Success(user)
}])

//模版列表
router.set('/templateList', [auth('_index'), async (ctx, next) => {
    const v = await new ListValidator().validate(ctx)
    const limit = v.get('query.limit')
    const page_index = v.get('query.page_index')
    const name = v.get('body.name')
    const TemplateTypeId = v.get('body.TemplateTypeId')
    const UserId = v.get('body.UserId')
    const where: any = { state: 1 }
    const typeWhere: any = {}
    name && (where.name = { [Op.substring]: name })
    TemplateTypeId && (typeWhere.id = TemplateTypeId)
    UserId && (where.UserId = UserId)
    const { rows, count } = await Template.findAndCountAll({
        attributes: {
            include: [[
                sequelize.literal(`(
            SELECT COUNT(*)
            FROM storeitems
            WHERE
                storeitems.TemplateId = Template.id
                AND
                storeitems.isSaled = 1
        )`),
                'count'
            ]]
        },
        where,
        include: [{ model: TemplateType, where: typeWhere, attributes: ['name'] }, ImgTemplate,
        { model: Material, through: { attributes: [] } }],
        distinct: true,
        limit: limit * 1,
        offset: (page_index - 1) * limit,
        order: [['state', 'DESC'], ['createdAt', 'DESC']]
    })
    throw new Success({ list: rows, total: count })
}])
//根据模版ID获取产品
router.set('/getStoreBytemplate', [auth('public'), async (ctx, next) => {
    const v = await new ListValidator().validate(ctx)
    const limit = v.get('query.limit')
    const page_index = v.get('query.page_index')
    const TemplateId = v.get('body.TemplateId')
    if (!TemplateId) throw new ParameterException('模版ID不存在')
    const { rows, count } = await StoreItem.findAndCountAll({
        where: { TemplateId, isSaled: false, UserId: { [Op.not]: null } },
        include: {
            model: User, attributes: ['nickname', 'phone', 'location', 'avatar', 'fullUrl'],
            //@ts-ignore
            include: { model: RoomNumber, include: { model: BlockNumber, include: Area } }
        },
        distinct: true,
        limit: limit * 1,
        offset: (page_index - 1) * limit,
    })
    throw new Success({ list: rows, total: count })
}])
//模版详情
router.set('/templateDetail', [auth('indexDetail'), async (ctx, next) => {
    const v = await new InfoValidator().validate(ctx)
    const id = v.get('query.id')
    const template = await Template.findOne({
        attributes: {
            include: [[
                sequelize.literal(`(
            SELECT COUNT(*)
            FROM storeitems
            WHERE
                storeitems.TemplateId = Template.id
        )`),
                'count'
            ]]
        },
        where: { id },
        include: [{ model: TemplateType, attributes: ['name'] }, ImgTemplate,
        { model: Material, through: { attributes: [] } }, { model: User, attributes: ['nickname', 'avatar', 'fullUrl', 'id'] }]
    })
    throw new Success(template)
}])

export { router }
